#ifndef MOCHA_DETAIL_EVENT_QUEUE_HPP_INCLUDED
#define MOCHA_DETAIL_EVENT_QUEUE_HPP_INCLUDED

/**
 * @file
 */

#include <string>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include "mocha/events.hpp"

namespace mocha {
/**
 * Event queue.
 * Exposes system events when pumped, which typically occurs at the end of each cycle.
 * @see event 
 */
class event_queue : public boost::noncopyable {
public:
	event_queue();
	~event_queue();
	/**
	 * Pumps the queue, pushing new events.
	 * No events are removed.
	 */
	void pump();
	/**
	 * Removes all events.
	 */
	void clear();
	/**
	 * Removes all events.
	 * @param events 
	 */
	void clear(std::vector<event>& events);
	/**
	 * Pushes an event onto the back of the queue.
	 */
	void push(const event& e);
	/**
	 * Pushes events onto the back of the queue.
	 * @param events Buffer of events.
	 */
	void push(const std::vector<event>& events);
	/**
	 * Pushes events onto the back of the queue.
	 * @param I Iterator type.
	 * @param begin 
	 * @param end 
	 */
	template<typename I>
	void push(I begin, I end) {
		// TODO: 
	}
	/**
	 * Pops (removes) the next event off the front of the queue.
	 * @param e Next event at the front of the queue. Unmodified if no such event exists.
	 * @return Non-zero if there was an event to pop, otherwise zero.
	 */
	int pop(event& e);
	/**
	 * Pops (removes) the next event matching a type mask, starting from the queue's front.
	 * @param e Next event matching a type mask. Unmodified if no such event exists.
	 * @param type Event type mask.
	 * @return Non-zero if a matching event was found, otherwise zero.
	 * @see pop_all
	 * @see event_type_mask
	 */
	int pop(event& e, int type);
	/**
	 * Pops (removes) all events matching a type mask.
	 * @param events 
	 * @param type Event type mask.
	 * @return 
	 * @see event_type_mask
	 */
	int pop_all(std::vector<event>& events, int type);
	/**
	 * Pops (removes) all events satisfying a predicate.
	 * @param P 
	 * @param events 
	 * @param f Predicate function.
	 * @return 
	 */
	template<typename P>
	int pop_if(std::vector<event>& events, P f) {
		return 0; // TODO: 
	}
};
}

#endif

